LOADING...

加载过慢请开启缓存(浏览器默认开启)

loading

Java复习款练习题

2023/8/22 后端

Collection集合习题

练习:Collection集合统计元素出现次数

给定以下代码,请定义方法listTest()统计集合中指定元素出现的次数,如”a”: 2,”b”: 2,”c” :1, “xxx”:0

   public static void main(String[] args) {
        Collection<String> list = new ArrayList<>();
        list.add("a");
        list.add("a");
        list.add("b");
        list.add("b");
        list.add("c");
        System.out.println("a:"+listTest(list, "a"));
        System.out.println("b:"+listTest(list, "b"));
        System.out.println("c:"+listTest(list, "c"));
        System.out.println("xxx:"+listTest(list, "xxx"));
    }
    private static int listTest(Collection<String> list, String s){
        int count = 0;
        for (String string : list){
            if (s.equals(string)){
                count++;
            }
        }
        return count;
    }

练习:Collection集合数组转集合

定义一个方法,要求此方法把int数组转成存有相同元素的集合(集合里面的元素是Integer),并返回。

    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6};
        ArrayList<Integer> arrayList = listTest(arr);
        System.out.println(arrayList);
    }
    public static ArrayList<Integer> listTest(int[] arr){
        ArrayList<Integer> list = new ArrayList<Integer>();
        for (Integer a : arr){
            list.add(a);
        }
        return list;
    }

练习:Collection集合集合转数组

定义一个集合,并把集合(集合里面的元素是Integer)转成存有相同元素的数组,并将结果输出在控制台。(可以使用Object[]数组类型接收转换的数组)

    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(100);
        list.add(200);
        list.add(300);
        Object[] obj = list.toArray();
        for (int i = 0; i < obj.length; i++) {
            System.out.println(obj[i]);
        }
    }

public Object[] toArray()

以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。返回的数组将是“安全的”,因为该列表不保留对它的引用。 (换句话说,这个方法必须分配一个新的数组)。 因此,调用者可以自由地修改返回的数组。

练习:Collection集合contains()方法使用

定义一个方法listTest(ArrayList < String > a1, String s),要求使用contains()方法判断a1集合里面是否包含s。

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("itcast");
        list.add("itheima");
        list.add("java");
        System.out.println(listTest(list,"Java"));
    }

    private static boolean listTest(ArrayList<String> a1, String s){
        if (a1.contains(s)){
            return true;
        }
        return false;
    }

练习:Collection集合isEmpty()方法的使用

定义一个方法listTest(ArrayList< String > a1), 要求使用isEmpty()判断a1里面是否有元素。

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("1");
        System.out.println(listTest(list));
    }
    public static boolean listTest(ArrayList<String>a1){
        if (a1.isEmpty()){
            return true;
        }
        return false;
    }

练习:简述迭代器的实现原理

当遍历集合时,首先通过调用集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。

Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,在调用Iterator的next()方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。

练习:Collection集合返回首次出现索引

定义一个方法listTest(ArrayList< Integer > a1, Integer s),要求返回s在a1里面第一次出现的索引,如果s没出现过返回-1。

    public static void main(String[] args) {
        //定义集合,添加数据
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        System.out.println(listTest(list,5));
    }
    private static int listTest(ArrayList<Integer>a1, Integer s){
        for (int i = 0; i < a1.size(); i++) {
            if (a1.get(i).equals(s)){
                return i;
            }
        }
        return -1;
    }

File类&递归&FileFilter习题

练习:检查文件是否存在,文件的创建

描述:检查D盘下是否存在文件a.txt,如果不存在则创建该文件。

操作步骤:
1.使用绝对路径创建对象关联到D盘的a.txt。
2.通过文件对象方法判断文件是否存在。
3.不存在则调用创建文件的方法创建文件。

    public static void main(String[] args) throws IOException {
        File f = new File("D:\\Clash\\aaa.txt");
        if (!f.exists()){
            f.createNewFile();
        }
    }

练习:单极文件夹的创建

描述:在D盘下创建一个名为bbb的文件夹。

操作步骤:
1.创建文件对象指定路径为d:/bbb
2.调用文件对象创建文件夹的方法

    public static void main(String[] args) throws IOException {
        File f = new File("D:\\Clash\\aaa");
        // File f = new File("D:\\Clash\\aaa\\bbb");
        f.mkdir();
        // f.mkdirs(); 创建多级文件夹
    }

练习:删除文件和文件夹

描述:将D盘下a.txt文件删除。将D盘下aaa文件夹删除,要求文件夹aaa是一个空文件夹。

操作步骤:

1.创建文件对象关联路径:d:/a.txt
2.调用文件对象删除文件的方法
3.创建文件对象关联路径:d:/aaa
4 调用文件对象删除文件夹的方法.

    public static void main(String[] args) {
        // 创建文件对象
        File f = new File("d:/a.txt");
        // 删除文件
        f.delete();
        
        // 创建文件夹对象
        File dir = new File("d:/aaa");
        // 删除文件夹
        dir.delete();
    }

获取文件信息:文件名,文件大小,文件的绝对路径,文件的父路径

描述:获取D盘aaa文件夹中b.txt文件的文件名,文件大小,文件的绝对路径和父路径等信息,并将信息输出在控制台。

操作步骤:

    public static void main(String[] args) {
        // 创建文件对象
        File f = new File("D:\\Clash\\a.txt");
        // 获得文件名
        String filename = f.getName();
        // 获得文件大小
        long filesize = f.length();
        // 获得文件的绝对路径
        String path = f.getAbsolutePath();
        // 获得父文件夹路径,返回字符串
        String parentPath = f.getParent();
        // 获得父文件夹路径,返回文件对象
        File parentFile = f.getParentFile();
        // 输出信息
        System.out.println("文件名:" + filename);
        System.out.println("文件大小:" + filesize);
        System.out.println("文件路径:" + path);
        System.out.println("文件父路径:" + parentPath);
        System.out.println("文件父路径:" + parentFile);
    }

练习:文件夹或文件的判断

描述:

1.判断File对象是否是文件,是文件则输出:xxx是一个文件,否则输出:xxx不是一个文件。
2.判断File对象是否是文件夹,是文件夹则输出:xxx是一个文件夹,否则输出:xxx不是一个文件夹。(xxx是文件名或文件夹名)

操作步骤:

1.创建两个文件对象分别关联到不同的文件,比如:d:/a.txt,d:/aaa
2.调用文件对象的判断是否是文件或是否是文件夹的方法
3.获得文件名,根据判断结果输出信息。

    public static void main(String[] args) {
       File f = new File("D:\\Clash\\a.txt");
       if (f.isFile()){
           System.out.println(f.getName() + "是文件");
       }else {
           System.out.println(f.getName() + "不是文件");
       }

       File f2 = new File("D:\\Clash");
       if (f2.isDirectory()){
           System.out.println(f2.getName() + "是文件夹");
       }else{
           System.out.println(f2.getName() + "不是文件夹");
       }
    }

练习:文件夹的获取方式

描述:

获取指定文件夹下所有的文件,并将所有文件的名字输出到控制台。
注意:不包含子文件夹下的文件

操作步骤:

1.创建文件对象关联到指定文件夹,比如:c:/aaa
2.调用文件对象的listFiles方法获得文件数组
3.遍历文件数组将每一个文件的名字输出到控制台

    public static void main(String[] args) {
        File f = new File("D:\\Clash");
        File[] files = f.listFiles();
        for (File file : files){
            System.out.println(file.getName());
        }
    }

List集合&Set集合习题

练习:List接口的特点

简述List接口的特点

★ 它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的读取顺序按照11、22、33的顺序完成的
★ 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)
★ 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素

练习:hashCode和equals方法

请简述HashSet去除重复元素的原理

★ 调用被添加元素的hashCode(), 和HashSet中已有元素的hasCode比较是否相同
★ 如果不同,直接存储
★ 如果相同,调用equals方法比较是否相同
★ 不相同,直接存储元素
★ 相同,认为是同一元素,不存储

练习:数据结构

简述常见的数据结构中元素的存储特点

★ 栈:stack,又称堆栈,对元素的存取特点是先进后出。即,存进去的元素,要在后它后面的元素一次取出后,才能取出该元素
★ 队列:queue,简称队,对元素的存取特点是先进先出。即,存进去的元素,要在后它前面的元素依次取出后,才能取出该元素
★ 数组:Array,是有序的元素序列,对元素的存储特点是:
1,查找元素快:通过索引,可以快速访问指定位置的元素
2.增删元素慢
(1).指定索引位置增加元素:需要创建一个新数组,将指定元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置
(2).指定索引位置删除元素:需要创建一个新数组,把原数组元素根据索引,复制到新数组对应索引的位置,原数组中指定索引位置元素不复制到新数组中
★ 链表:linkedlist 对元素的存取有如下的特点:
**(1).**多个结点之间,通过地址进行连接。例如,多个人手拉手,每个人使用自己的 右手拉住下个人的左手,依次类推,这样多个人就连在一起了。
**(2).**查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素。
(3).增删元素快:
增加元素:只需要修改连接下个元素的地址即可。
删除元素:只需要修改连接下个元素的地址即可。

练习:Comparable和Comparator比较器

简述 Comparable Comparator 两个接口的区别

Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能再类中实现compareTo()一次,不能经常修改的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sortArrays.sort 从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。

练习:LinkedList方法的使用

根据要求练习LinkedList方法:

(1).基本方法:add, set, get, remove, clear, size等方法;
(2).特有方法:addFirst, addLast, getFirst, getLast, removeFirst, removeLast, push, pop, clear等方法。

(1).基本方法
public static void main(String[] args) {
        // 1.创建LinkedList
        LinkedList<String> arr = new LinkedList<String>();

        // 2.使用add方法添加元素
        arr.add("西门吹雪");
        arr.add("西门吹雪");
        arr.add("西门吹雪");
        arr.add("西门吹风");
        arr.add("西门吹水");

        // 3.使用add方法在指定索引添加元素
        arr.add(2, "西门吹雨");

        // 4.使用set方法修改指定位置索引
        arr.set(0, "东门");

        for (String str : arr) {
            System.out.println(str);
        }
        System.out.println("--------------");
        // 5.使用get方法获取指定索引的元素
        System.out.println(arr.get(1));

        // 6.使用size方法获取集合大小
        System.out.println(arr.size());

        // 7.使用remove方法删除指定索引的元素
        arr.remove(3);

        // 8.使用clear清空集合中的元素
        arr.clear();
        System.out.println(arr);
    }
}
(2).特有方法
public static void main(String[] args) {
        // 1.创建LinkedList
        LinkedList<String> linked = new LinkedList<String>();

        // 2.使用add方法添加元素
        linked.add("周杰伦");
        linked.add("周星驰");
        linked.add("周华健");
        linked.add("周润发");

        // 3.使用addFirst添加元素到集合最前面
        linked.addFirst("周传雄");

        // 4.使用addLast添加元素到集合最后面
        linked.addLast("周渝民");

        System.out.println(linked);

        // 5.使用getFirst获取集合第一个元素
        System.out.println(linked.getFirst());

        // 6.使用getLast获取集合最后一个元素
        System.out.println(linked.getLast());

        // 7.使用removeLast删除集合第一个元素
        String first = linked.removeFirst();
        System.out.println(first);

        // 8.使用removeLast删除集合最后一个元素
        String last = linked.removeLast();
        System.out.println(last);
        System.out.println(linked);


        // 9.使用pop弹出第一个元素
        String p = linked.pop();
        System.out.println(p);

        // 10.使用push在集合开头插入元素
        linked.push("周立波");
        System.out.println(linked);

        // 11.使用clear清空集合
        linked.clear();
        System.out.println(linked);
    }
}

练习:HashSet存储自定义类型

定义人类,包含姓名和年龄属性。创建4个人存储到HashSet中,姓名和年龄相同的人看做同一人不存储。

// 1.定义Person类.包好姓名年龄属性,重写hashCode()和equals()方法
public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person)) return false;

        Person person = (Person) o;

        if (age != person.age) return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
ublic class HashSetTest01 {
    public static void main(String[] args) {
        // 2.创建HashSet用于存储Person类型
        HashSet<Person> hashSet = new HashSet<Person>();

        // 3.添加多个Person到HashSet中
        hashSet.add(new Person("王昭君", 21));
        hashSet.add(new Person("西施", 21));
        hashSet.add(new Person("杨玉环", 20));
        hashSet.add(new Person("貂蝉", 19));
        hashSet.add(new Person("杨玉环", 20));
        hashSet.add(new Person("貂蝉", 19));

        // 4.遍历获取HashSet中的内容
        for (Person p : hashSet) {
            System.out.println(p);
        }
    }
}

练习:List集合元素替换

向list集合添加姓名{张三,李四,王五,二丫,钱六,孙七}, 将二丫替换为王小丫

public class ListTest01 {
    public static void main(String[] args) {
        //1.创建List集合对象
        List<String> list = new ArrayList<>();
        //2.存入数据
        list.add("张三");
        list.add("李四");
        list.add("王五");
        list.add("二丫");
        list.add("钱六");
        list.add("孙七");
        //3.遍历集合,找到"二丫",便将其替换为"王小丫"
        //利用普通for循环遍历List集合
        for(int i = 0;i<list.size();i++) {
            //获取当前元素
            String thisName = list.get(i);
            //如果当前元素是"二丫"
            if("二丫".equals(thisName)) {
                //将其改为"王小丫"
                list.set(i, "王小丫");
            }
        }
        System.out.println(list);
    }
}

//   使用增强for获取LinkedHashSet中的元素
        for (String str : list){
           if ("二丫".equals(str)){
                System.out.println(list);
           }
        }

练习:LinkedHashSet基本使用

使用LinkedHashSet存储以下元素:”王昭君”,”王昭君”,”西施”,”杨玉环”,”貂蝉”。使用迭代器和增强for循环遍历LinkedHashSet。

public class LinkedHashSetTest01 {
    public static void main(String[] args) {
        // 1.创建LinkedHashSet
        LinkedHashSet<String> lhSet = new LinkedHashSet<String>();
        // 2.使用add方法添加元素到LinkedHashSet
        lhSet.add("王昭君");
        lhSet.add("王昭君");
        lhSet.add("王昭君");
        lhSet.add("西施");
        lhSet.add("杨玉环");
        lhSet.add("貂蝉");
        // 3.使用迭代器获取LinkedHashSet中的元素
        Iterator<String> iterator = lhSet.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        // 4.使用增强for获取LinkedHashSet中的元素
        System.out.println("---------------------");
        for (String string : lhSet) {
            System.out.println(string);
        }
    }
}

练习:Collections工具类使用

ArrayList集合中有如下内容: {33,11,77,55},使用Collections.sort()对ArrayList集合中的数据进行排序,并打印出排序后的结果

public class CollectionsTest01 {
    public static void main(String[] args) {
        // 1.创建ArrayList
        ArrayList<Integer> arr = new ArrayList<Integer>();

        // 2.使用add方法添加{33,11,77,55}四个元素
        arr.add(33);
        arr.add(11);
        arr.add(77);
        arr.add(55);

        // 3.调用Collections的sort方法,对集合排序
        Collections.sort(arr);

        // 4.使用增强for遍历ArrayList集合
        for (Integer integer : arr) {
            System.out.println(integer);
        }
    }
}

Map集合习题

练习:Map接口的特点

请简述Map 的特点

★ Map每个元素由键与值两部分组成
★ Map键不能重复,每个键对应一个值
★ 键和值可以为null

练习:Entry键值对对象

说出Entry键值对对象遍历Map集合的原理

Map中存放的是两种对象,一种称为Key(键),一种称为value(值),它们在Map中是一一对应关系,这一种对象又称做Map中的一个Entry(项)。Entry将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map集合时,就可以从每个键值对(Entry)对象中获取对应的键与对应的值。

练习:Map接口中的常用方法

请使用Map集合的方法完成添加元素,根据键删除,以及根据键获取值操作。
    public static void main(String[] args) {
        HashMap<String, String> hm = new HashMap<String, String>();
        hm.put("黄晓明", "Baby");
        hm.put("邓超", "孙俪");
        hm.put("李晨", "范冰冰");
        hm.put("大黑牛", "范冰冰");
        String v1 = hm.put("李晨", "白百合");
        String string = hm.get("大黑牛");
        String v2 = hm.remove("大黑牛");
        System.out.println(v2);
        System.out.println(hm);
    }
//  范冰冰  {邓超=孙俪, 李晨=白百合, 黄晓明=Baby}

练习:Map接口中的方法

往一个Map集合中添加若干元素。获取Map中的所有value,并使用增强for和迭代器遍历输出每个value。

public static void main(String[] args) {
        // 1.创建HashMap
        HashMap<String, String> hm = new HashMap<String, String>();

        // 2.使用put添加元素
        hm.put("黄晓明", "Baby");
        hm.put("邓超", "孙俪");
        hm.put("李晨", "范冰冰");
        hm.put("大黑牛", "范冰冰");

        // 3.使用Map的values方法获取到所有的value
        Collection<String> values = hm.values();

        // 4.使用增强for获取每个value
        for (String value : values) {
            System.out.println(value);
        }

        System.out.println("----------------");
        // 5.使用迭代器获取每个value
        Iterator<String> itr = values.iterator();
        while (itr.hasNext()) {
            System.out.println(itr.next());
        }
    }

练习:HashMap存储键是自定义对象是String

请使用Map集合存储自定义数据类型Car做键,对应的价格做值。并使用keySet和entrySet两种方式遍历Map集合。

        // 1.定义汽车类.包含名称和价格属性,重写hashCode和equals方法
    public class Car {
        private String name;
        private String color;
        ...
    }
---------------------------------------------------
    public static void main(String[] args) {
         // 2.创建HashMapkey保存汽车对象,value是汽车价格
        HashMap<Car, Integer> hm = new HashMap<>();

        // 3.添加汽车到HashMap中
        Car c1 = new Car("长安奔奔", "黄色");
        Car c3 = new Car("奇瑞QQ", "黑色");
        Car c2 = new Car("铃木奥拓", "白色");

        hm.put(c1, 10000);
        hm.put(c2, 20000);
        hm.put(c3, 30000);

         // 4.使用keySet方式遍历Map
        Set<Car> keySet = hm.keySet();
        for (Car c : keySet) {
        // 根据key获取value
            Integer value = hm.get(c);
            System.out.println(c.getName() + "," + c.getColor() + " - " + value);
        }

        System.out.println("-------------");

        // 5.使用entrySet方式遍历Map
        Set<Map.Entry<Car, Integer>> entrySet = hm.entrySet();
        for (Map.Entry<Car, Integer> entry : entrySet) {
            Car key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key.getName() + "," + key.getColor() + " - " + value);
        }
    }

public Set<Map.Entry<K,V>> entrySet()
返回此地图中包含的映射的Set视图。 该集合由地图支持,因此对地图的更改将反映在集合中,反之亦然。 如果在集合中的迭代正在进行时修改映射(除了通过迭代器自己的remove操作,或者通过迭代器返回的映射条目上的setValue操作),迭代的结果是未定义的。 该组支持元件移除,即从映射中相应的映射,经由Iterator.removeSet.removeremoveAllretainAllclear操作。 它不支持addaddAll操作。

练习:Map集合的使用(一)

现在有一个map集合如下:
     Map<Integer,String> map = new HashMap<Integer, String>();
     map.put(1, "张三丰");
     map.put(2, "周芷若");
     map.put(3, "汪峰");
     map.put(4, "灭绝师太");

要求:

1.遍历集合,并将序号与对应人名打印。
2.向该map集合中插入一个编码为5姓名为李晓红的信息
3.移除该map中的编号为1的信息
4.将map集合中编号为2的姓名信息修改为”周林”

    public static void main(String[] args) {
        // 1.定义HashMap,编号作为key,姓名作为value
        Map<Integer, String> map = new HashMap<Integer, String>();
        // 2.使用put方法添加元素
        map.put(1, "张三丰");
        map.put(2, "周芷若");
        map.put(3, "汪峰");
        map.put(4, "灭绝师太");
        // 3.使用keySet+增强for迭代map中的元素,并打印
        Set<Integer> keySet = map.keySet();
        for (Integer key : keySet) {
            String value = map.get(key);
            System.out.println(key + " -- " + value);
        }
        // 4.使用put向该map集合中插入一个编码为5姓名为李晓红的信息
        map.put(5, "李晓红");
        // 5.使用remove移除该map中的编号为1的信息
        map.remove(1);
        // 6.使用put将map集合中编号为2的姓名信息修改为"周林"
        map.put(2, "周林");
        System.out.println(map);
    }

练习:Map集合的使用(二)

有2个数组
第一个数组内容为:[黑龙江省,浙江省,江西省,广东省,福建省],
第二个数组为:[哈尔滨,杭州,南昌,广州,福州],将第一个数组元素作为key
第二个数组元素作为value存储到Map集合中。如{黑龙江省=哈尔滨, 浙江省=杭州, …}

    public static void main(String[] args) {
        // 1.定义第一个数组arr1
        String[] arr1 = {"黑龙江省", "浙江省", "江西省", "广东省", "福建省"};
        // 2.定义第二个数组arr2
        String[] arr2 = {"哈尔滨", "杭州", "南昌", "广州", "福州"};

        // 3.创建HashMap,key存放省,value存放市
        HashMap<String, String> hm = new HashMap<>();

        // 4.使用普通for循环遍历arr1
        for (int i = 0; i < arr1.length; i++) {
        // 5.根据索引到arr1中获取到省
            String key = arr1[i];
        // 6.根据索引到arr2中获取到省会城市
            String value = arr2[i];

        // 7.将省和省会城市添加到HashMap中
            hm.put(key, value);
        }
        // 8.输出HashMap中的内容
        System.out.println(hm);
    }

Math类习题

练习:实现字符串123反转

使用字符数组保存原始字符,利用Random类生成随机索引。

        public class Test1 {
            public static void main(String[] args) {
                Scanner scanner = new Scanner(System.in);
                String next = scanner.next();
                System.out.println("录入的字符串:" + next);
                String s = reverseStr(next);
                System.out.println("反转的字符串:"+ s);
            }
        
            public static String reverseStr(String  str){
                String s = "";
                char[] chars = str.toCharArray();
                for (int i = chars.length - 1; i >= 0; i--) {
                    s +=chars[i] ;
                }
                return s;
            }
        }

toCharArray() 方法将字符串转换为字符数组

练习:键盘录入QQ号判断正确性

必须是5-12位数字,0不能开头

public class Test1 {
    public static void main(String[] args) {
        //1.键盘输入一个qq号码字符串
        Scanner sc = new Scanner(System.in);
        String qq = sc.next();
        //2.调用checkQQ (String qq)方法内实现验证。
        boolean isOK = checkQQ(qq);
        //3.打印验证的结果
        System.out.println("这个QQ号码是否正确:" + isOK);
    }

    /*
     * 定义方法:checkQQ (String qq)方法内实现验证
     * 指定方法的名称:checkQQ
     * 指定方法的参数:String qq
     * 指定方法的返回值:boolean
     */
    public static boolean checkQQ(String qq) {
        //1.验证字符串的长度5-12位之间;
        if (qq.length() < 5 || qq.length() > 12) {
            return false; //说明qq号码的长度不正确
        }
        //2.验证首位字符不能是字符0;只能是字符'1'--'9'
        if (qq.charAt(0) == '0') {
            return false;
        }
        //3.验证字符串中的每个字符都必须是数字字符‘0’-‘9’之间的字符
        for (int i = 0; i < qq.length(); i++) {
            char ch = qq.charAt(i);
            //判断字符是否在 数字字符‘0’-‘9’之间的字符
            if (ch < '0' || ch > '9') {
                return false;//说明qq号码中含有非数字字符
            }
        }
        //4.上述验证都通过了,说明qq号码是正确的
        return true;
    }
 }

练习:大小写字符转换并统计次数

键盘录入一个大字符串,再录入一个小字符串。统计小字符串在大字符串中出现的次数。

   /*
* 分析以下需求,并用代码实现
1.键盘录入一个大字符串,再录入一个小字符串
2.统计小字符串在大字符串中出现的次数
3.代码运行打印格式:
请输入大字符串:woaiheima,heimabutongyubaima,wulunheimahaishibaima,zhaodaogongzuojiushihaoma
请输入小字符串:heima
控制台输出:小字符串heima,在大字符串woaiheima,heimabutongyubaima,wulunheimahaishibaima,zhaodaogongzuojiushihaoma中共出现3次
             */

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 1.键盘录入一个大字符串,再录入一个小字符串
        System.out.print("请输入大字符串:");
        String big = sc.nextLine();
        System.out.print("请输入小字符串:");
        String small = sc.nextLine();
        // 2.统计小字符串在大字符串中出现的次数
        int count = getCount(big, small);
        // 3.代码运行打印格式:
        System.out.println("小字符串" + small + ",在大字符串中共出现" + count + "次");
    }

    /*
     * 方法功能:统计小字符串在大字符串中出现的次数
     * 参数:big 代表大字符串
     * 参数:small 代表小字符串
     * 返回值:小字符串在大字符串中出现的次数
     */
    public static int getCount(String big, String small) {
        int index = 0;
        int count = 0;
        /*
         * indexOf(String str, int fromIndex)
         * 该方法作用:从fromIndex位置开始查找,字符串str第一次出现的位置;若没找到,放回-1
         */
        while ((index = big.indexOf(small, index)) != -1) {
            index++;
            count++;
        }
        return count;
    }

练习:随机小数保留两位

生成一个随机100内小数,转换为保留两位小数的字符串,不考虑四舍五入的问题。

    public static void main(String[] args) {
        double random = Math.random()*100;
        System.out.println("随机数为:");
        System.out.println(random);
        String str = random + " ";
        int index = str.indexOf(".");
        String substring = str.substring(0, index + 3);
        System.out.println("转换为");
        System.out.println(substring);
    }
// substring(int strat, int end)中第一个参数是开始位置,第二个参数是结束位置.

练习:筛选字符串

定义ArrayList集合,存入多个字符串。长度大于5的字符串,打印删除后的集合。

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("bca");
        list.add("dadfa");
        list.add("dddaaa");
        list.add("你好啊");
        list.add("我来啦,你干嘛呢");
        list.add("别跑啊");
        System.out.println("源字符串:");
        System.out.println(list);
        delStrsFromList01(list);
    }
    private static void delStrsFromList01(ArrayList<String> list){
        ArrayList<String> list2 = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            String str = list.get(i);
            if (str.length() > 3){
                list2.add(str);
            }
        }
        for (Object str : list2){
            list.remove(str);
        }
        System.out.println("新字符:" + list);
    }

练习:回文字符串

判断回文字符串。如果一个字符串,从前向后读和从后向前读,都是一个字符串,称为回文串,比如mom,dad,noon。

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String next = scanner.next();
        boolean p = isP(next);
        System.out.println(
                "回文数:" + p
        );
    }

    public static boolean isP(String str) {
        int start = 0;
        int end = str.length() - 1;
        while (start < end) {
            if (str.charAt(start) != str.charAt(end)) {
                return false;
            }
            start++;
            end--;
        }
        return true;
    }

charAt() 方法用于返回指定索引处的字符。索引范围为从 0 到 length() - 1。

练习:模拟简单计算器

模拟简单计算器,可以运算+,—,*,/,%。

  • 接收三个参数,一个整数,一个运算符,另一个整数。( ‘5’ ‘+’ ‘7’ )
  • 计算出运算结果。
  • 无法运算时,返回null。
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int a = scanner.nextInt();
        String next = scanner.next();
        int b = scanner.nextInt();
        String count = count(a, next, b);
        System.out.println(a +next +b +"="+count);
    }

    public static String count(int a, String op , int b ){
        int r=0;
        if ("+".equals(op)){
            r = a+b;
        }else  if ("-".equals(op)){
            r = a-b;
        }else  if ("*".equals(op)){
            r = a*b;
        }else  if ("/".equals(op)){
            r = a/b;
        }else  if ("%".equals(op)){
            r = a%b;
        }else {
            return null;
        }
        return r+"";
    }

练习:密码是否合法

校验密码是否合法。合法返回true

  • 必须至少8个字符。
  • 必须至少2个大写字符。超越两个就要依次遍历 for循环
  • 必须只有字母和数字。
    public static void main(String[] args) {
        String s = "qweRY123";
        System.out.println(s+"密码是否合法"+isTrue(s));
    }
    private static boolean isTrue(String s){
        if (s.length()<8){
            return false;
        }

        int countA = 0;
        char[] chars = s.toCharArray();
        for (int i = 0; i < s.length(); i++) {
            char ch = chars[i];
            //2个大写字母
            if (ch >= 'A' && ch <= 'Z'){
                countA++;
            }
            //字母数字
            if ((ch < '0'|| ch>'9') && (ch < 'A'|| ch>'Z')&&(ch < 'a'|| ch>'z')) {
                return false;
            }
        }
        if (countA < 2){
            return false;
        }
        return true;
    }

练习:模拟用户登录

模拟用户登录。

  • 定义用户类,属性为用户名和密码。
  • 使用集合存储多个用户对象。
  • 录入用户和密码,对比用户信息,匹配成功登录成功,否则登录失败。
  • 登录失败时,当用户名错误,提示没有该用户。
  • 登录失败时,当密码错误时,提示密码有误。

jack-1234 rose-5678 tom-0000
请输入用户名:rose
请输入密码:5678
登录结果:登录成功

public class User {
    private String username;
    private String pwd;
}
------------------------------------------
public class Test {
    static ArrayList<User> list = new ArrayList<>();
    static {
        list.add(new User("jack", "1234"));
        list.add(new User("rose", "5678"));
        list.add(new User("tom", "0000"));
        for (int i = 0; i < list.size(); i++) {
            list.get(i).show();
        }
    }
    public static void main(String[] args) {
        
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = sc.nextLine();
        System.out.println("请输入密码:");
        String password = sc.nextLine();
        User u = new User(username, password);
        String login = login(u);
        System.out.println("登录结果:" + login);
    }
    public static String login(User user) {
        String msg = "";
        String n = user.getUsername();
        String p = user.getPwd();
        for (int i = 0; i < list.size(); i++) {
            User u = list.get(i);
            String name = u.getUsername();
            String pwd = u.getPwd();
            if (name.equals(n)){
                if (pwd.equals(p)){
                    return "登录成功";
                }else {
                    return "密码错误";
                }
            }else {
                msg = "用户名不存在";
                continue;
                }
            }
        return msg;
        }
    }

static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。[ 在此代码内适用于login方法中的list.size() ]
static代码块只在类加载时执行,类是用类加载器来读取的,类加载器是带有一个缓存区的,
它会把读取到的类缓存起来,所以在一次虚拟机运行期间,一个类只会被加载一次,这样的话静态代码块只会运行一次

Object类&Date类&Calender(日期)类&StringBuilder类

练习:简述String和Object中的equals

简述String类中的equals方法 与 Object类中的equals方法的不同点

String类中的equals方法是用来判断两个对象的内容是否相同,而Object 类中的equals方法是用来判断两个对象是否是同一个对象,所谓同一个对象指的是内存中的同一块存储空间。

练习:Object类的toString方法

    public class ToStringTest{
        static int i = 1;
        public static void main(String args[]){
            System.out.println("love " + new ToStringTest());//love java
            ToStringTest a = new ToStringTest();
            a.i++;
            System.out.println("me " + a.i);//me 2
        }
        public String toString(){
            System.out.print("I ");//I
            return "java ";
        }
    }

运行结果:I love java me 2
原因:当执行代码的时候,首先加载静态变量,然后执行main方法,由于main方法内部第一行代码为输出语句,里面new了此类对象,当执行此行代码时会先创建了本类的对象,由于此类重写了toString方法,会先执行toString方法的打印输出,然后返回“java ”,再执行main方法第一行打印输出。在Java中“System.out.println(类对象名);”实际输出的是该对象的toString()方法返回的字符串,即括号中的内容等价于类对象名.toString(),toString方法的好处是在碰到println方法的时候会被自动调用,不用显示的写出来。

练习:Object类equals方法

看下列程序,不运行说结果,写出答案后,并在IntelliJ IDEA中运行看看自己给的答案与运行结果是否正确,并分析原因。

    (1)
        String s1 = new String("abc");
        String s2 = "abc";
        System.out.println(s1 == s2);         //false
        System.out.println(s1.equals(s2));  //true
    (2)
        String s1 = "abc";
              String s2 = "abc";
        System.out.println(s1 == s2);         //true
        System.out.println(s1.equals(s2));     //true
    (3)
        String s1 = "a" + "b" + "c";
              String s2 = "abc";
        System.out.println(s1 == s2);        //true
        System.out.println(s1.equals(s2));     //true
    (4)
        String s1 = "ab";
             String s2 = "abc";
             String s3 = s1 + "c";
        System.out.println(s3 == s2);             //false
              System.out.println(s3.equals(s2));  //true

练习:StringBuilder类与String类的区别

简述StringBuilder类与String类的区别

String类的对象内容不可改变,所以每当进行字符串拼接时,总是会在内存中创建一个新的对象,所以经常改变内容的字符串最好不要用String,因为每次生成对象都会对系统性能产生影响

StringBuilder又称为可变字符序列,是JDK5.0中新增加的一个类,它是一个类似于String的字符串缓冲区,通过某些方法调用可以改变该序列的长度和内容。即它是一个容器,容器中可以装很多字符串,并且能够对其中的字符串进行各种操作。它的内部拥有一个数组用来存放字符串内容,进行字符串拼接时,直接在数组中加入新内容,StringBuilder会自动维护数组的扩容

练习:Date类的使用

获取当前的日期, 并把这个日期转换为指定格式的字符串, 如2088-08-08 08:08:08

    public static void main(String[] args) {
        //获取当前日期对象 now;
        Date now = new Date();
        //创建SimpleDateFormat对象 df,并制定日期格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //调用df的format(Date  date) 方法,传入now; 接收返回的字符串
        String datestr = df.format(now);
        //打印这个字符串
        System.out.println(datestr);
    }

练习:DateFormat类方法的使用

使用SimpleDateFormat类,把2018-03-04转换为2018年03月04日

    public static void main(String[] args) throws ParseException {
        //创建SimpleDateFormat对象df1,指定日期模式为yyyy-MM-dd
        SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
        //调用df1的parse(String str)方法传入2018-03-04,得到对应日期类型
        Date date = df1.parse("2018-03-04");
        //创建日期格式化对象df2,在获取格式化对象时可以指定风格
        DateFormat df2 = new SimpleDateFormat("yyyy年MM月dd日");
        //调用df2的format(Date date) 传入刚才转换的日期
        String str = df2.format(date);
        System.out.println(str);
    }

public Date parse(String text, ParsePosition pos)
从字符串中解析文本,产生一个Date

练习:Calendar类方法的使用

用程序判断2018年2月14日是星期几。

public static void main(String[] args) {
        //创建Calendar对象
        Calendar c = Calendar.getInstance();
        //将给定的日历字段设置到Calendar对象中
        c.set(Calendar.YEAR, 2018);
        c.set(Calendar.MONTH, 1);
        c.set(Calendar.DATE, 14);
        //设置年
        int year = c.get(Calendar.YEAR);
        //设置月
        int month = c.get(Calendar.MONTH)+1;
        //设置日
        int date = c.get(Calendar.DATE);
        //设置星期
        char week = getWeek(c.get(Calendar.DAY_OF_WEEK));
        //输出结果
        System.out.println(year+"年"+month+"月"+date+"日是星期"+week);
    }
    //定义方法,获取星期汉字
    public static char getWeek(int a){
        char[] c = {' ','日','一','二','三','四','五','六'};
        return c[a];
    }
}

Random类&ArrayList集合习题

练习:随机验证码

  • 随机生成十组六位字符组成的验证码。
  • 验证码由大小写字母、数字字符组成。

开发提示:使用字符数组保存原始字符,利用Random类生成随机索引。

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            String s = verifyCode();
            System.out.println("随机验证码:" + s);
        }
    }
    public static String verifyCode(){
        char[] arr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
        Random random = new Random();
        String code = "";
        for (int i = 0; i < 6; i++) {
            int index = random.nextInt(arr.length);
            code  += arr[index];
        }
        return code;
    }

练习:输入学生信息保存到集合

键盘录入学生信息,保存到集合中。

  • 循环录入的方式,1:表示继续录入,0:表示结束录入。
  • 定义学生类,属性为姓名,年龄,使用学生对象保存录入数据。
  • 使用ArrayList集合,保存学生对象,录入结束后,遍历集合。
public class Student {
    private String name;
    private int age;
     public void show(){
        System.out.println("姓名: "+ name + " " + "年龄: " + age);
    }
}
----------------------------------
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            ArrayList<Student> list = new ArrayList<>();
            while (true) {
                System.out.println("1.录入信息 0.退出");
                int i = scanner.nextInt();
                switch (i) {
                    case 1:
                        inputStu(list , scanner);
                        break;
                    case 0:
                        System.out.println("录入完毕");
                }
                if (i == 0){
                    break;
                }
            }
    
            for (int i = 0; i < list.size(); i++) {
                Student student = list.get(i);
                student.show();
            }
        }
    
        private static void inputStu(ArrayList<Student> list , Scanner sc) {
            System.out.println("请输入姓名:");
            String name = sc.next();
            System.out.println("请输入年龄:");
            int age = sc.nextInt();
            Student student = new Student(name, age);
            list.add(student);
        }
    }

练习:随机数 次数打印

统计数字出现次数。

  • 定义getNumList方法,随机生成100个数字,数字范围从1到10。
  • 定义printCount方法,统计每个数字出现的次数并打印到控制台。
    public class Test4 {
        public static void main(String[] args) {
            ArrayList<Integer> numList = getNumList();
            //  统计字符数组中字母出现次数
            printCount(numList);
        }
        public static void printCount(ArrayList<Integer> list) {
            int[] count = new int[10];
            // 对应保存数字出现的次数
            for (int i = 0; i < list.size(); i++) {
                int c = list.get(i);
                count[c-1]++;
            }
            // 打印数字和次数
            for (int i = 0 ; i < count.length; i++) {
                    System.out.println("数字:"+(i+1) + "--" + count[i]+"次");
            }
        }
        public static ArrayList<Integer> getNumList() {
            ArrayList<Integer> list = new ArrayList<>();
            Random r = new Random();
            for (int i = 0; i < 100; i++) {
                int x = r.nextInt(10) + 1;
                list.add(x);
            }
            return list;
        }
    }    

练习:需求实现

模拟统计班级考试分数分布情况,分别统计100-80,79-60,59-40,39-0各个阶段的人数。

  • 定义getScoreList方法,随机生成50个数字,数字范围从0到100。
  • 定义countScore方法,统计各个阶段的分数个数。
  • 定义printCount方法,打印各个阶段的统计结果。
    public static void main(String[] args) {
        ArrayList<Integer> scoreList = getScoreList(); //获取随机分数
        ArrayList<Integer> countList = countScore(scoreList); //定义计数的变量
        printCount(countList);
    }
    public static ArrayList<Integer> countScore(ArrayList<Integer> scoreList) {
        ArrayList<Integer> countList = new ArrayList<>();
        int count100 = 0;
        int count79 = 0;
        int count59 = 0;
        int count39 = 0;

        for (int i = 0; i < scoreList.size(); i++) {
            Integer score = scoreList.get(i);
            if (score <= 100 && score >= 80) {
                count100++;
            } else if (score <= 79 && score >= 60) {
                count79++;
            } else if (score <= 59 && score >= 40) {
                count59++;
            } else {
                count39++;
            }
        }

        countList.add(count100);
        countList.add(count79);
        countList.add(count59);
        countList.add(count39);

        return countList;
    }

    private static ArrayList<Integer> getScoreList(){
        ArrayList<Integer> list = new ArrayList<>();
        Random r = new Random();
        for (int i = 0; i < 50; i++) {
            int x = r.nextInt(100);
            list.add(x);
        }
        return list;
    }

    private static void printCount(ArrayList<Integer> countList) {
        int start = 100;
        int end = 80;
        for (int i = 0; i < countList.size(); i++) {
            Integer integer = countList.get(i);
            System.out.println(start + "\t分 --" + end + " \t分:" + integer+"人");
            if (i == 0){
                start-=21;
                end -=20;
            }else if (i == countList.size()-2){
                start-=20;
                end-=40;
            }else {
                start -= 20;
                end -= 20;
            }
        }
    }

练习:添加移除展示元素

自定义MyList类,实现存取元素的功能。

  • 定义add方法,可以保存元素,添加MyList尾部。
  • 定义remove方法,可以获取到最后添加的元素,并从MyList中移除该元素。
  • 定义show方法,可以展示MyList中的元素。
public static void main(String[] args) {
        MyList myList = new MyList();
        for (int i = 0; i < 3; i++) {
            myList.add(i);
        }
        System.out.println("添加元素后:");
        myList.show();

        Integer remove = myList.remove();
        System.out.println("获取元素:");
        System.out.println(remove);
        System.out.println("获取元素后:");
        myList.show();
    }
}

class MyList {
    ArrayList<Integer> ml = new ArrayList<>();

    public void add(Integer i) {
        ml.add(i);
    }

    public Integer remove() {
        Integer remove = ml.remove(ml.size() - 1);
        return remove;
    }

    public void show() {
        System.out.println(ml);
    }
}

线程&同步习题

练习:多线程开启

请描述Thread类中的start()方法与run()方法的区别

线程对象调用run()方法不开启线程,仅是对象调用方法。
线程对象调用start()方法开启线程,并让jvm调用run()方法在开启的线程中执行。

练习:创建多线程

请描述创建线程的两种方法
  • 将类声明为Thread的子类

①.定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。
②.创建Thread子类的实例,即创建了线程对象
③.调用线程对象的start()方法来启动该线程

  • 声明一个类实现Runnable接口

①.定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体
②,创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,Thread对象才是真正的线程对象
③.调用线程对象的start()方法来启动线程

练习:多线程

请编写程序,分别打印主线程的名称和子线程的名称

要求使用两种方式实现:
第一种方式:继承Thread类。
第二种方法:实现Runnable接口。

操作步骤描述

  • 继承Thread类

①.定义一个子线程的类,继承Thread类
②.在子线程类中重写run方法,在run方法中打印子线程的名称
③.定义一个测试类
④.在main方法中打印主线程的名称
⑤.在main方法中创建子线程对象
⑥.调用子线程对象的start方法,开启子线程

// 1.定义一个子线程的类,继承Thread类;
public class SubThread extends Thread{
// 2.在子线程类中重写run方法,在run方法中打印子线程的名称;
    public void run(){
    // 打印子线程的名称
      System.out.println("subThread:" + Thread.currentThread().getName());
    }
}
// 3.定义一个测试类
public class ThreadDemo{
    public static void main(String[] args){
// 4.在main方法中打印主线程的名称;
    System.out.println("main:" + Thread.currentThread().getName());
// 5.在main方法中创建子线程对象;
    SubThread st = new SubThread();
// 6.调用子线程对象的start方法,开启子线程。
    st.start();
    }
}
  • 实现Runnable接口

①.定义一个子任务类,实现Runnable接口
②.在子任务中重写run方法,在run方法中打印子线程的名称
③.定义一个测试类
④.在main方法中打印主线程的名称;
⑤.在main方法中创建一个子任务对象;
⑥.在main方法中创建一个Thread类的对象,并把子任务对象传递给Thread类的构造方法;
⑦.调用Thread类对象的start方法开启子线程;

// 1.定义一个子任务类,实现Runnable接口。
public class SubRunnable implements Runnable{
    @Override
    public void run() {
// 2.在子任务类中重写run方法,在run方法中打印子线程的名称。
    System.out.println("SubRunnable:"+ Thread.currentThread().getName());
// 3.定义一个测试类。
   }
}
public class RunnableDemo {
    public static void main(String[] args) {
// 4.在main方法中打印主线程的名称。
    System.out.println("RunnableDemo:"+ Thread.currentThread().getName());
// 5.在main方法中创建一个子任务对象。
    SubRunnable r = new SubRunnable();
// 6.在main方法中创建一个Thread类的对象,并把子任务对象传递给Thread类的                         构造方法。
    Thread t = new Thread(r);
// 7.调用Thread类对象的start方法开启子线程。
    t.start();
 }
}

练习:实现Runnable接口的优势

请描述实现Runnable接口比继承Thread类所具有的优势:

①.适合多个相同的程序代码的线程去共享同一个资源
②.可以避免java中的单继承的局限性
③.增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和数据独立。
④.线程池只能放入实现Runnable或callable类线程,不能直接放入继承Thread的类

练习:多线程

创建多线程对象,开启多线程。在子线程中输出1-100之间的偶数,主线程输出1-100之间的奇数

自定义线程类

public class MyThread extends Thread {
    /**
     * 重写run方法,完成该线程执行的逻辑
     */
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            if (i % 2 == 0) {
                System.out.println("子线程打印输出偶数:" + i);
            }
        }
    }
    public class Test11 {
        public static void main(String[] args) {
            //创建自定义线程对象
            MyThread mt = new MyThread();
            //开启线程
            mt.start();
            //在主方法中执行for循环
            for (int i = 1; i <= 100; i++) { 
                if (i % 2 == 1) {
                    System.out.println("主线程打印输出奇数:" + i);
                }
            }
        }
    }

练习:线程状态

请描述在线程的生命周期中, 有几种状态呢 ?

1.NEW(新建) 线程刚被创建,但是并未启动。

2.Runnable(可运行)
线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理器。

3.Blocked(锁阻塞)
当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。

4.Waiting(无限等待)
一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。

5.Timed Waiting(计时等待)
同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、Object.wait。

6.Teminated(被终止)
因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。

线程池&lambda表达式习题

练习:线程池概念

请描述什么是线程池

线程池:其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复用户创建线程而消耗过多的资源

练习:线程池优点

请描述合理利用线程池能够带来的三个好处

1,降低资源消耗。减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可以执行多个任务
2.提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行
3.提高线程的可管理性。可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。

练习:Lambda表达式

请列举Lambda语法的省略规则

在Lambda标准格式的基础上,使用省略句写法的规则为:
1.小括号内参数的类型可以省略
2.如果小括号内有且只有一个参数,则小括号可以省略
3.如果大括号内有且只有一个语句,则无论是否有返回值,都可以省略大括号、return、关键字以及语句分号

练习:Lambda表达式

请列举Lambda表达式的3个组成部分,并解释说明

Lambda标准格式Lambda省去面向对象的条条框框,格式由3个部分组成:一些参数、一个箭头、一段代码
Lambda表达式的标准格式
1.小括号内的语法与传统方法参数列表一致:无参数则留空,多个参数则用逗号分割
2.”—>”是新引入的语法格式,代表指向动作
3.大括号内的语法与传统方法体要求基本一致

练习:Lambda表达式

请描述Lambda的使用前提

Lambda的语法非常简介,完全没有面向对象复杂的束缚。但是使用时有几个问题需要特别注意:
1.使用Lambda必须具有接口,且要求接口中有且只有一个抽象方法。无论是JDK内置的Runnable、Comparator接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才能使用Lambda。
2.使用Lambda必须具有上下文推断。也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例

练习:多线程

代码实现打印输出1-99
public class Test06 {
    public int start = 1;
    public int end = 99;

public static void main(String[] args) {
    new Test06().method();
 }

public void method() {
    //插入代码处
         Runnable a = () -> {
      for (int i = start; i <end; i++) {
        System.out.println(i);
      }
    };
      Thread t = new Thread(a);
      t.start();
     }
}

练习:多线程

请问该程序的运行结果是什么? 如有问题,请说明原因。
public class Test07implements Runnable {
    public static void main(String[] args) {
      Thread t = new Thread(new Test07());
      t.start();
      }

public void run(int num) {
    for (int i = 0; i < num; i++) {
       System.out.println(i);
    }
  }
}

在编译时期就会报错

​ Test类没有重写Runnable接口中的run()方法

​ public void run(int num)不是Runnable接口中的run()方法。

注意:Runnable接口中的run()方法,参数列表为空,不带参数。

练习:线程池练习

使用线程池创建多线程。模拟同学找老师学习Java。

1.创建线程池对象,包含2个线程。从线程池中获取线程对象,然后调用MyRunnable中的run()。
2.在MyRunnable实现类中,首先在控制台打印需求,“我需要一个老师”。模拟需要2秒钟时间老师可以过来指导学生,并在控制台打印老师的姓名。最后,在控制台打印“教我java,教完后,老师回到了办公室”;

class Test implements Runnable{
    @Override
    public void run() {
        System.out.println("我要一个老师");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("老师来了" + Thread.currentThread().getName());
        System.out.println("教我Java,教完后,老师回到了办公室");
    }
}

class ThreadPoolDemo{
    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(2);
        Test r = new Test();
        service.submit(r);//线程1
        service.submit(r);//线程2
        service.submit(r);//线程3
    }
}

练习:Lambda(无参无返回)

给定一个导演 Director接口,内含唯一的抽象方法makeMovie,且无参数、无返回值,使用lambda表达式在Test中完成调用。

interface Director{
    void makeMovie();
}
public class Test {
    public static void main(String[] args) {
        // TODO 请使用Lambda【省略格式】调用invokeDirect方法
        invokeDirect(()-> System.out.println("拍电影啦"));
    }
    private static void invokeDirect(Director director){
        director.makeMovie();
    }
}

练习:Lambda(有参有返回)

给定一个计算器 Calculator 接口,内含抽象方法 calc (减法),其功能是可以将两个数字进行相减,并返回差值。使用Lambda表达式在Test中完成调用

interface Calculator{
    int calc(int a, int b);
}
public class Test {
    public static void main(String[] args) {
        // TODO 请分别使用Lambda【标准格式】及【省略格式】调用invokeCalc方法来计算130-120的结果ß
        invokeCalc(130, 120, (int a, int b) -> {
            return a - b;
        }); //标准格式
        invokeCalc(130,120,(a,b)-> a-b); //省略模式
    }
    private static void invokeCalc(int a, int b, Calculator calculator){
        int result = calculator.calc(a,b);
        System.out.println("结果是:" + result);
    }
}

Stream流

练习一:Pedicate接口使用

请在测试类main方法中完成以下需求

已知有Integer[] arr = {-12345, 9999, 520, 0,-38,-7758520,941213}

a) 使用lambda表达式创建Predicate对象p1,p1能判断整数是否是自然数(大于等于0)

b) 使用lambda表达式创建Predicate对象p2,p2能判断整数的绝对值是否大于100

c) 使用lambda表达式创建Predicate对象p3,p3能判断整数是否是偶数

遍历arr,仅利用已创建的Predicate对象(不使用任何逻辑运算符),完成以下需求

​ i. 打印自然数的个数

​ ii. 打印负整数的个数

​ iii. 打印绝对值大于100的偶数的个数

​ iv. 打印是负整数或偶数的数的个数

public static void main(String[] args) {
        Integer[] arr = {-12345, 9999, 520, 0,-38,-7758520,941213};

        //a)   使用lambda表达式创建Predicate对象p1,p1能判断整数是否是自然数
        Predicate<Integer> p1 = (s) -> s>=0;
        //b)   使用lambda表达式创建Predicate对象p2,p2能判断整数的绝对值是否大于100
        Predicate<Integer> p2 = (s) -> Math.abs(s)>100;
        //c)   使用lambda表达式创建Predicate对象p3,p3能判断整数是否是偶数
        Predicate<Integer> p3 = (s) -> s%2==0;

        //e)   遍历arr,仅利用已创建的Predicate对象(不使用任何逻辑运算符),完成以下需求
        int count1 = 0;
        int count2 = 0;
        int count3 = 0;
        int count4 = 0;
        for (Integer i : arr) {
            //统计自然数个数
            if (p1.test(i)){
                count1++;
            }
            //统计负整数个数
            if (p1.negate().test(i)){
                count2++;
            }
            //统计绝对值大于100的偶数个数
            if (p2.and(p3).test(i)){
                count3++;
            }
            //统计是负整数或偶数的数的个数
            if (p1.negate().or(p3).test(i)){
                count4++;
            }
        }
        //分别打印结果
        System.out.println("自然数的个数为:"+count1);
        System.out.println("负整数的个数为:"+count2);
        System.out.println("绝对值大于100的偶数的个数为:"+count3);
        System.out.println("是负整数或偶数的数的个数为:"+count4);
    }

练习:Function接口使用

[这是一个功能界面,因此可以用Lambda表达式或方法引用的赋值对象]

Interface Function<T,R>
T:函数输入的类型
R:函数结果的类型

Interface Map<K,V>
K:由此地图维护的键的类型
V:映射值的类型

1.使用lambda表达式分别将以下功能封装到Function对象中

a) 求Integer类型ArrayList中所有元素的平均数

b) 将Map < String,Integer > 中value存到ArrayList < Integer >中

2.已知学生成绩如下

姓名 成绩
岑小村 59
谷天洛 82
渣渣辉 98
蓝小月 65
皮几万 70

3.以学生姓名为key成绩为value创建集合并存储数据,使用刚刚创建的Function对象求学生的平均成绩

    public static void main(String[] args) {
        //1.   使用lambda表达式分别将以下功能封装到Function对象中
        //a)   求Integer类型ArrayList中所有元素的平均数
        Function<ArrayList<Integer>,Integer> f1 = (list)->{
            Integer sum = 0;
            for (Integer i : list) {
                sum+=i;
            }
            return sum/list.size();
        };

        //b)   将Map<String,Integer>中value存到ArrayList<Integer>中
        Function<Map<String,Integer>,ArrayList<Integer>> f2 = (map)->{
            /*ArrayList<Integer> list = new ArrayList<>();
            for (String s : map.keySet()) {
                Integer i = map.get(s);
                list.add(i);
            }*/
            Collection<Integer> values = map.values();
            ArrayList<Integer> list = new ArrayList<>();
            list.addAll(values);
            return list;
        };
        //2 将学生姓名和成绩封装到map中
        Map<String,Integer> map = new HashMap<String, Integer>();
        map.put("岑小村", 59);
        map.put("谷天洛", 82);
        map.put("渣渣辉", 98);
        map.put("蓝小月", 65);
        map.put("皮几万", 70);

        //利用Function求平均成绩
        Integer avg = f2.andThen(f1).apply(map);
        System.out.println("学生平均成绩为:"+avg);
    }

练习:获取流

简述单列集合、双列集合、数组分别如何获取Stream流对象,并进行演示

1.java.util.Collection接口中加入了default方法 stream()获取流对象,因此其所有实现类均可通过此方式获取流

2.java.util.Map接口想要获取流,先通过KeySet()、values()或entrySet()方法获取键、值或键值对的单列集合,再通过stream()获取流对象

3.数组获取流,使用Stream接口中的静态方法of(T...values)获取流
public static void main(String[] args) {
  List<String> list = new ArrayList<>();
  Stream<String> stream1 = list.stream();
  Set<String> set = new HashSet<>();
  Map<String, String> map = new HashMap<>();

  Stream<String> stream2 = set.stream();
  Stream<String> keyStream = map.keySet().stream();
  Stream<String> valueStream = map.values().stream();
  Stream<Map.Entry<String,String>>entryStream = map.entrySet().stream();

  String[] array = {"东邪", "西毒", "南帝", "北丐", "中神通"};
  Stream<String> stream = Stream.of(array);
}

练习:过滤[filter]、结果收集(数组)

有如下7个元素黄药师,冯蘅,郭靖,黄蓉,郭芙,郭襄,郭破虏,使用Stream将以郭字开头的元素存入新数组

public class Test {
    public static void main(String[] args) {
          Stream<String> stream = Stream.of("黄药师", "冯蘅", "郭靖", "黄蓉", "郭芙", "郭襄", "郭破虏");
        String[] guos = stream.filter(s -> s.startsWith("郭")).toArray(String[]::new);
     }
}
// filter 返回由与此给定谓词匹配的此流的元素组成的流。
// toArray 返回一个包含此流的元素的数组 结果: 一个包含此流的元素的数组

练习:n 取用前几个[limit]、跳过前几个[skip]

已知ArrayList集合中有如下元素{陈玄风、梅超风、陆乘风、曲灵风、武眠风、冯默风、罗玉风},使用Stream
1,取出前2个元素并在控制台打印输出。
2.取出后2个元素并在控制台打印输出。

import java.util.ArrayList;
    public class Test04 {
      public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("陈玄风");
        list.add("梅超风");
        list.add("陆乘风");
        list.add("曲灵风");
        list.add("武眠风");
        list.add("冯默风");
        list.add("罗玉风");

        list.stream().limit(2).forEach(System.out::println);
        list.stream().skip(list.size() - 2).forEach(System.out::println);
    }
}

练习:n 映射[map]、逐一消费[forEach]

有如下整数1,-2,-3,4,-5
使用Stream取元素绝对值并打印

import java.util.stream.Stream;
   public class Test {
      public static void main(String[] args) {
          Stream<Integer> stream = Stream.of(1, -2, -3, 4,-5);
        stream.map(Math::abs).forEach(System.out::println);
     }
}

练习:组合[concat]、结果收集[list]

已知数组arr1中有如下元素{郭靖,杨康},arr2中有如下元素{黄蓉,穆念慈},使用Stream将二者合并到List集合

import java.util.stream.Stream;
  public class Test {
    public static void main(String[] args) {
          Stream<String> streamA = Stream.of("郭靖", "杨康");
        Stream<String> streamB = Stream.of("黄蓉", "穆念慈");
        List<String> strList = Stream.concat(streamA, streamB).collect(Collectors.toList());
     }
}

练习:获取并发流

请分别写出获取并发流的两种方式。

public class Test {
    public static void main(String[] args) {
          Collection<String> coll = new ArrayList<>();
          Stream<String> parallelStream1 = coll.parallelStream();
        Stream<Integer> parallelStream2 = Stream.of(100, 200, 300, 400).parallel();
     }
}

函数式接口习题

练习:函数式接口

①. 定义一个函数式接口CurrentTimePrinter,其中抽象方法void printCurrentTime(),使用注解@FunctionalInterface
②. 在测试类中定义static void showLongTime(CurrentTimePrinter timePrinter),该方法的预期行为是使用timePrinter打印系统当前毫秒值
③. 测试showLongTime(),通过lambda表达式完成需求

@FunctionalInterface
public interface CurrentTimePrinter
{
    void printCurrenTime();
}

public class Test01 {
    public static void main(String[] args) {
        showLongTime(()->System.out.println(System.currentTimeMillis()));
    }

    public static void showLongTime(CurrentTimePrinter timePrinter){
        timePrinter.printCurrentTime();
    }
}

练习:函数式接口

①. 定义一个函数式接口IntCalc,其中抽象方法int calc(int a , int b),使用注解@FunctionalInterface
②. 在测试类中定义static void getProduct(int a , int b ,IntCalc calc), 该方法的预期行为是使用calc得到a和b的乘积并打印结果
③. 测试getProduct(),通过lambda表达式完成需求

IntCalc接口:

@FunctionalInterface
 public interface IntCalc {
   int calc(int a, int b);
 }

测试类:

public class Test02 {
   public static void main(String[] args) {
     getProduct(2,3,(a,b)->a*b);
   }
   public static void getProduct(int a, int b, IntCalc intCalc){
     int product = intCalc.calc(a,b);
     System.out.println(product);

   }
}

练习:静态方法引用

①. 定义一个函数式接口NumberToString,其中抽象方法String convert(int num),使用注解@FunctionalInterface
②. 在测试类中定义static void decToHex(int num ,NumberToString nts), 该方法的预期行为是使用nts将一个十进制整数转换成十六进制表示的字符串,**tips:已知该行为与Integer类中的toHexString方法一致**
③. 测试decToHex (),使用方法引用完成需求

interface NumberToString{
    String convert(int num);
}

public class Test {
    public static void main(String[] args) {
        decToHex(999, Integer::toHexString);
    }

    public static void decToHex(int num ,NumberToString nts){
        String convert = nts.convert(num);
        System.out.println(convert);
    }

}

字节流&字符流&Properties集合习题

练习:字节输出流写出字节数据

利用字节输出流一次写一个字节的方式,向D盘的a.txt文件输出字符‘a’

操作步骤:

1.创建字节输出流FileOutputStream对象并指定文件路径。
2.调用字节输出流的write(int byte)方法写出数据

public class Test01_01 {
    public static void main(String[] args) throws IOException {
        // 1.创建字节输出流FileOutputStream对象并指定文件路径。
        FileOutputStream fos = new FileOutputStream("d:/a.txt");
        // 2.调用字节输出流的write(byte[] buf)方法写出数据。
        byte[] buf = "i love java".getBytes();
        // 2.调用字节输出流的write(int byte)方法写出数据
        fos.write(97);
        // 3.关闭流
        fos.close();
    }
}

练习:文件的续写和换行输出

在D盘下,有一c.txt 文件中内容为:HelloWorld
在c.txt文件原内容基础上,添加五句 I love java,而且要实现一句一行操作(注:原文不可覆盖)。利用字节输出流对象往C盘下c.txt文件输出5句:”i love java”

操作步骤:

1.利用两个参数的构造方法创建字节输出流对象,参数一指定文件路径,参数二指定为true
2.调用字节输出流的write()方法写入数据,在每一行后面加上换行符:”\r\n”

public class Test01_03 {
    public static void main(String[] args) throws IOException{
        // 1.创建字节输出流FileOutputStream对象并指定文件路径,并追加方式
        FileOutputStream fos = new FileOutputStream("c:/c.txt",true);
        // 2.调用字节输出流的write方法写出数据
        // 2.1 要输出的字符串
        String content = "i love java \r\n";
        for (int i = 0; i< 5; i++) {
            fos.write(content.getBytes());
        }
        // 3.关闭流
        fos.close();
    }
}
/*
    定义变量接收读取的字节
        int len = -1;
        // 循环从流中读取数据
        while((len = fis.read()) != -1) {
        System.out.print(new String(buffer,0,len));
}

*/

练习:字节流复制文件

描述: 利用字节流将E盘下的a.png图片复制到D盘下(文件名保存一致)

要求:一次读写一个字节的方式

操作步骤:

1.创建字节输入流对象关联文件路径:E盘下的a.png
2.创建字节输出流对象关联文件路径:D盘下的a.png
3.使用循环不断从字节输入流读取一个字节,每读取一个字节就利用输出流写出一个字节。
4.关闭流,释放资源

public class Test01_06 {
    public static void main(String[] args) throws IOException {
        // 创建字节输入流对象并关联文件
        FileInputStream fis = new FileInputStream("e:/a.png");
        // 创建字节输出流对象并关联文件
        FileOutputStream fos = new FileOutputStream("d:/a.png");
        // 定义变量接收读取的字节数
        int len = -1;
        // 循环读取图片数据
        while((len = fis.read()) != -1) {
            // 每读取一个字节的数据就写出到目标文件中
            fos.write(len);
        }
        // 关闭流
        fis.close();
        fos.close();
    }

练习:IO对象Properties结合使用,设置properties文件

我有一个文本文件score.txt,我知道数据是键值对形式的,但是不知道内容是什么。
请写一个程序判断是否有”lisi”这样的键存在,如果有就改变其实为”100”
score.txt文件内容如下:
zhangsan = 90 lisi = 80 wangwu = 85
操作步骤:
1.创建一个空的Properties集合
2.读取数据到集合中
3.遍历集合,获取到每一个key
4.判断当前的key 是否为 “lisi”,如果是就把”lisi”的值设置为100
5.把集合中所有的信息,重新存储到文件中

void store(OutputStream out, String comments)
此适合使用load(InputStream)方法加载到Properties表中的格式,将此Propeirties表中的属性列表(键和元素对写入输出流)
public class Test02_06 {
    public static void main(String[] args) throws IOException {
//1:创建一个空的集合
        Properties prop = new Properties();
//2:读取数据到集合中
        prop.load(new FileInputStream("score.txt"));
//3:遍历集合,获取到每一个key
        Set<String> keys = prop.stringPropertyNames();
//获取到每一个key
        for (String key : keys) {
//4:判断当前的key 是否为 "lisi"
            if ("lisi".equals(key)) {
//把"lisi"的值设置为100
                prop.setProperty(key, "100");
            }
        }
//把集合中所有的信息,重新存储到文件中
        prop.store(new FileOutputStream("score.txt"), "haha");
    }
}

缓冲流&转换流习题

练习:高效字节输出流写出字节数据

描述: 利用高效字节输出流往C盘下的d.txt文件输出一个字节数。

操作步骤:

1.创建字节输出流对象关联文件路径
2.利用字节输出流对象创建高效字节输出流对象
3.调用高效字节输出流对象的write方法写出一个字节
4.关闭高效流,释放资源。

public class Test01_01 {
    public static void main(String[] args) throws IOException {
        // 创建字节输出流FileOutputStream对象并指定文件路径。
        FileOutputStream fos = new FileOutputStream("c:\\d.txt");
        // 利用字节输出流创建高效字节输出流对象
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        // 调用高效字节输出流对象的write(int byte)方法写出一个字节数据
        bos.write(97);
        // 关闭流
        bos.close();
    }
}

练习:高效字节输出流写出字节数组数据

描述: 利用高效字节输出流往C盘下的e.txt文件写出一个字节数组数据,如写出:”i love java”

操作步骤:

1.创建字节输出流对象关联文件路径
2.利用字节输出流对象创建高效字节输出流对象
3.定义字符串存放要输出的数据,然后将字符串转换为字节数组。
4.调用高效字节输出流对象的write方法将字节数组输出。
5.关闭高效流。

public class Test01_02 {
    public static void main(String[] args) throws IOException {
        // 创建字节输出流FileOutputStream对象并指定文件路径。
        FileOutputStream fos = new FileOutputStream("c:\\e.txt");
        // 利用字节输出流创建高效字节输出流对象
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        // 调用高效字节输出流对象的write(byte[] buff)方法写出一个字节数据
        bos.write("i love java".getBytes());
        // 关闭流
        bos.close();
    }
}

练习:高效流文件复制

描述: 利用高效字节输入流和高效字节输出流完成文件的复制。

要求:

1.将C盘下的c.png文件复制到D盘下
2.一次读写一个字节数组方式复制

操作步骤:

①.创建字节输入流对象并关联文件路径
②.利用字节输入流对象创建高效字节输入流对象
③.创建字节输出流对象并关联文件路径
④.利用字节输出流对象创建高效字节输出流对象
⑤.创建字节数组用来存放读取的字节数
⑥.利用高效字节输入流循环读取文件数据,每读取一个字节数组,利用高效字节输出流对象将字节数组的内容输出到目标文件中。直到读取到文件末尾。
⑦.关闭高效流对象

public class Test01_03 {
    public static void main(String[] args) throws IOException{
        // 创建字节输入流对象并关联文件路径
        FileInputStream fis = new FileInputStream("c:\\c.png");
        // 利用字节输出流对象创建高效字节输出流对象
        BufferedInputStream bis = new BufferedInputStream(fis);
        // 创建字节输出流对象并指定文件路径。
        FileOutputStream fos = new FileOutputStream("d:\\c.png");
        // 利用字节输出流创建高效字节输出流对象
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        // 定义字节数组接收读取的字节
        byte[] buffer = new byte[1024];
        // 定义变量接收读取的字节数
        int len = -1;
        // 循环读取图片数据
        while((len = bis.read(buffer)) != -1) {
            // 每读取一个字节的数据就写出到目标文件中
            bos.write(buffer,0,len);
        }
        // 关闭流
        bis.close();
        bos.close();
    }
}

练习:高效字符流和集合的综合使用

描述:

分析以下需求,并用代码实现
实现一个验证码小程序,要求如下:
① 在项目根目录下新建一个文件:data.txt,键盘录入3个字符串验证码,并存入data.txt中,要求一个验证码占一行;
② 键盘录入一个需要被校验的验证码,如果输入的验证码在data.txt中存在:在控制台提示验证成功,如果不存在控制台提示验证失败

public class Test {
    public static void main(String[] args) throws IOException {
        writeString2File();
        verifyCode();
    }

    private static void writeString2File() throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter(new File("D:\\Clash\\a.txt")));
        String line = null;
        Scanner sc = new Scanner(System.in);
        for (int i = 0; i < 3; i++) {
            System.out.println("请输入第"+(i+1)+"个字符串验证码");
            line = sc.nextLine();
            bw.write(line);
            bw.newLine();
        }
        bw.close();
    }

    private static void verifyCode() throws IOException {
        ArrayList<String> list = new ArrayList<>();
        BufferedReader br = new BufferedReader(new FileReader(new File("D:\\Clash\\a.txt")));
        String line = null;
        while(null!=(line = br.readLine())){
        list.add(line);
    }
        br.close();
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个验证码");
        String code = sc.nextLine();
        if (list.contains(code)){
            System.out.println("验证成功");
        }else {
            System.out.println("验证失败");
        }
    }
}

练习:转换输出流的使用

描述: 现有一字符串:”我爱Java”。将该字符串保存到当前项目根目录下的a.txt文件中。

要求:使用gbk编码保存。
注意:idea的默认编码是utf-8,所以可以通过fileàsettingsàfile encodings设置为gbk格式,否则打开a.txt文件看到的将会是乱码。

操作步骤:

1.创建文件字节输出流关联目标文件
2.根据文件字节输出流创建转换输出流对象,并指定编码字符集为:gbk
3.调用流对象的方法将字符串写出到文件中。
4.关闭流并释放资源。

public class Test01_05 {
    public static void main(String[] args) throws IOException{
        // 要保存的字符串
        String content = "我爱Java";
        // 创建字节输出流对象
        FileOutputStream fos = new FileOutputStream("a.txt");
        // 创建转换输出流对象
        OutputStreamWriter osw = new OutputStreamWriter(fos, "gbk");
        // 调用方法写出数据
        osw.write(content);
        // 关闭流释放资源
        osw.close();
    }
}

练习:转换输入流的使用

描述: 利用转换输入流将当前项目根目录下使用gbk编码的a.txt文件的内容读取出来,并打印在控制台上。

要求:不能出现乱码的情况。
操作步骤:

1.创建字节输入流对象指定文件路径。
2.根据字节输入流对象创建转换输入流对象并指定字符集编码为:gbk
3.调用转换输入流对象的读取方法读取内容
4.关闭流释放资源

public class Test01_06 {
    public static void main(String[] args) throws IOException{
        // 创建字节输入流对象并关联文件
        FileInputStream fis = new FileInputStream("a.txt");
        // 创建转换输入流对象
        InputStreamReader isr = new InputStreamReader(fis,"gbk");
        // 定义字符数组存放读取的内容
        char[] buffer = newchar[1024];
        // 定义变量接收读取的字符个数
        intlen = -1;
        while((len = isr.read(buffer)) != -1) {
            System.out.print(new String(buffer,0,len));
        }
        // 关闭流
        isr.close();
    }
}

继承&抽象类习题

概念

什么叫做类与类的继承,作用是什么?

就是子类继承父类的属性和行为,使得子类对象具有与父亲相同的属性、相同的行为;
作用是子类复用父类的内容

继承后,父类与子类之间,各成员有什么样的影响?

成员变量:
不重名,就没有影响;重名,就近使用,使用super分区父类变量

构造方法:
无影响,但是子类构造方法默认调用父类构造方法

成员方法:
不重名,没有影响;重名,子类重写父类方法

子类中,如何调用父类的成员?如何使用本类的成员?

父类成员方法:super.方法名
父类非私有成员变量:super.变量名
子类成员方法:this.方法名
子类成员变量:this.变量名

抽象方法与普通成员方法有什么区别?

抽象方法使用abstract关键字修饰,没有方法体;成员方法有方法体

抽象类与普通类有什么区别?

方法:
抽象类可以包含抽象方法和成员方法;普通类不可以包含抽象方法,只有成员方法

对象:
抽象类不可以创建对象;普通类可以创建对象

练习:语法练习

  • 语法点:继承,抽象类

  • 输出A类中numa:10、B类中numb:20、C类中numc:30

abstract  class A{
    int numa = 10;
    public abstract void showA();
}

abstract class B extends A{
    int numb = 20;
    public abstract void showB();
}

class C extends B{
    int numc = 30;

    @Override
    public void showA() {
        System.out.println("A类中numa:"+numa);
    }

    @Override
    public void showB() {
        System.out.println("B类中numb:"+numb);

    }
    public void showC(){
        System.out.println("C类中numc:"+numc);
    }
}
public class Test {
    public static void main(String[] args) {
        C c = new C();
        c.showA();
        c.showB();
        c.showC();
    }
}

练习:语法练习

  • 语法点:继承,抽象类
  • 输出动物种类:鸭子,年龄:2岁、 入院原因:感冒、 症状为:发烧

编写步骤:

  1. 模拟农学院动物医疗系统信息。
  2. 定义抽象家禽类(Poultry)
    1. 私有成员变量:动物种类(name),症状(symptom),年龄(age), 病因(illness)
    2. 提供空参和带参构造方法
    3. 成员方法:
      1. 抽象方法症状(showSymptom)
      2. 普通方法基本信息(showMsg)
      3. 提供setXxx和getXxx方法
  3. 定义普通鸭子类(Duck)
    1. 提供空参和带参构造方法
    2. 重写showSymptom方法,打印症状信息。
public class Test3 {
    public static void main(String[] args) {
        Duck duck = new Duck("鸭子", "感冒", "发烧", 2);
        duck.showMsg();
        duck.showSymptom();
    }
}

/*
1.定义抽象家禽类(Poultry)
*/
abstract class Poultry {
    //    i.成员变量(私有):

    private String name;
    private String illness;

    // 症状(symptom)
    private String symptom;
    //    年龄(age)
    private int age;

    //    ii.成员方法:  showSymptom
    public abstract void showSymptom();

    // 成员方法:  showMsg
    public void showMsg() {
        System.out.print("动物种类:" + name);
        System.out.println(",年龄:" + age + "岁");
        System.out.println("入院原因:" + illness);
    }

    //    iii.提供空参和带参构造方法
    public Poultry() {
        super();
    }

    public Poultry(String name, String illness, String symptom, int age) {
        this.name = name;
        this.illness = illness;
        this.symptom = symptom;
        this.age = age;
    }

    //    iv.提供setXxx和getXxx方法
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getIllness() {
        return illness;
    }

    public void setIllness(String illness) {
        this.illness = illness;
    }

    public String getSymptom() {
        return symptom;
    }

    public void setSymptom(String symptom) {
        this.symptom = symptom;
    }
}

// Duck 类

class Duck extends Poultry {

    public Duck() {

    }

    public Duck(String name, String illness, String symptom, int age) {

        super(name, illness, symptom, age);

    }

    @Override

    public void showSymptom() {

        System.out.println("症状为:" + getSymptom());

    }

}

练习:语法练习

  • 语法点:继承

  • 输出:王小平老师,讲授Java课、 李小乐同学,考试得了90分

编写步骤:

  1. 模拟教学管理系统师生信息。
  2. 定义Person类。
    1. 属性:姓名、年龄
    2. 构造方法:无参构造方法,有参构造方法
    3. 成员方法:getXxx方法,setXxx方法,显示基本信息showMsg方法
  3. 定义Teacher类,继承Person
    1. 属性:学科
    2. 构造方法:无参构造方法,有参构造方法
    3. 成员方法:getXxx方法,setXxx方法,讲课方法
  4. 定义Student类,继承Person
    1. 属性:分数
    2. 构造方法:无参构造方法,有参构造方法
    3. 成员方法:getXxx方法,setXxx方法,考试方法
public class Test {

    public static void main(String[] args) {
        //        i.创建老师对象t,并把名称赋值为”王小平”,年龄赋值为30,工资赋值为8000
        Teacher t = new Teacher("王小平", 30, "Java");
        //        iii.调用老师对象t的讲解方法
        t.teach();

        //        iv.创建学生对象 s,并把名称赋值为”李小乐”,年龄赋值为14,成绩赋值为90分.
        Student s = new Student("李小乐", 14, 90);
        //        vi.调用学生对象 s 的考试方法
        s.exam();
    }
}

class Person {
    // 名称(name)
    private String name;
    //    年龄(age)
    private int age;

    //    空参构造
    public Person() {
    }
    //  带参构造
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // setXxx和getXxx方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
/*
 2.定义老师类(Teacher),继承Person类
 */
class Teacher extends Person {
    //    course(科目)
    private String course;
    //    空参构造
    public Teacher() {
    }
    //    带参构造方法
    public Teacher(String name,int age, String course) {
        super(name,age);
        this.course = course;
    }

    //    提供setXxx和getXxx方法
    public String getCourse() {
        return course;
    }
    public void setCourse(String course) {
        this.course = course;
    }

    public void teach() {
        System.out.println(getName() +"老师,讲授"+course +"课");
    }
}
/*
 3.定义学生类(Student),继承Person类
 */
class Student extends Person {
    //    score(成绩)
    private int score;
    //    无参构造
    public Student() {
        super();
    }
    //    带参构造
    public Student(String name, int age,int score) {
        super(name, age);
        this.score = score;
    }

    //    提供setXxx和getXxx方法
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }

    public void exam(){
        System.out.println(getName()+"同学,考试得了:"+ score +"分");
    }
}

练习:语法练习

  • 语法点:继承

  • 编写步骤

    1. 模拟汽车网站信息。
    2. 定义汽车Auto类
      1. 属性:品牌,车长,价格
    3. 定义SUV继承Auto类
      1. 属性:小型车车长标准值:4295,中型车车长标准值:5070。
      2. 定义判断车型方法
        1. 判断小型车:小于小型车车长标准值
        2. 判断大型车:大于中型车车长标准值
        3. 判断中型车:大于小型车车长标准值并且小于等于中型车车长标准值
    4. 测试类中,创建若干SUV对象,保存到集合,遍历集合,输出中型SUV。
public class Test5 {
    public static void main(String[] args) {
        // 创建SUV对象
        SUV suv1 = new SUV(5079, 750000);
        SUV suv2 = new SUV(4813, 760000);
        SUV suv3 = new SUV(4270, 127800);
        SUV suv4 = new SUV(4545, 188800);

        //添加到集合中
        ArrayList<SUV> list = new ArrayList<>();
        list.add(suv1);
        list.add(suv2);
        list.add(suv3);
        list.add(suv4);

        // 遍历集合,查询中型SUV
        for (int i = 0; i < list.size(); i++) {
            SUV suv = list.get(i);
            if (suv.midSUV()){
                suv.showMsg();
            }
        }
    }
}
// 定义汽车类
class Auto {
    private String type;
    private double length;
    private double price;

    public Auto() {
    }

    public Auto(String type, double length, double price) {
        this.type = type;
        this.length = length;
        this.price = price;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        this.length = length;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public void showMsg() {
        System.out.println("车型:" + type);
        System.out.println("\t价格:" + price);
        System.out.println("\t车长:" + length);

    }

}

// 定义SUV类
class SUV extends Auto {
    // 车长标准
    private int miniLength = 4295;
    private int midLength = 5070;

    public SUV(double length, double price) {
        super("SUV", length, price);
    }
    // 判断 小型车
    public boolean miniSUV() {
        return getLength() <= miniLength;
    }

    // 判断 大型车
    public boolean largeSUV() {
        return getLength() > midLength;
    }

    // 判断 中型车
    public boolean midSUV() {
        return getLength() > miniLength && getLength() <= midLength;
    }
}

接口&多态

概念辨析

什么是接口,如何定义接口?
  • 接口,是java语言中一种类型,是方法的集合
  • 使用interface关键字定义接口,其中可以定义抽象方法,默认方法,私有方法,静态方法等方法
什么叫做多态,条件是什么?

一类事物的行为,具有多种表现形式
条件:

  • 继承或实现[二选一]
  • 方法的重新
  • 父类引用指向子类对象
使用多态特性,带来了什么样的好处?

增强方法的扩展性和复用性

使用多态特性,注意什么样的弊端?

由于类型的提升,导致调用子类对象特有的方法,必须向下转型。

练习:接口

输出AAAA\n BBBB

编写步骤:

  1. 定义接口A,普通类B实现接口A
  2. A接口中,定义抽象方法showA。
  3. A接口中,定义默认方法showB。
  4. B类中,重写showA方法
  5. 测试类中,创建B类对象,调用showA方法,showB方法。
interface A{
    public abstract void showA(); //抽象方法
    public default void showB(){ //默认方法
        System.out.println("BBB");
    }
}

class B implements A{
    @Override
    public void showA() {
        System.out.println("AAAA");
    }
}

public class Test {
    public static void main(String[] args) {
        B b = new B();
        b.showA();
        b.showB();

    }
}

练习:接口

输出AAA\n BBBB BBBB BBBB BBBB\n CCCC CCCC CCCC CCCC

编写步骤:

  1. 定义接口A,普通类B实现接口A。
  2. A接口中,定义抽象方法showA。
  3. A接口中,定义私有方法show10(String str),循环打印10次str。
  4. A接口中,定义默认方法showB10,showC10,分别调用show10方法,传入参数。
  5. 测试类中,创建B对象,调用showA方法,showB10方法,showC10方法
interface AA{
    public abstract void showA();
    private void show10(String str){
        for (int i = 0; i < 10; i++) {
            System.out.print(str + " ");
        }
        System.out.println();
    }
    public default void show10B(){
        show10("BBBB");
    }
    public default void show10C(){
        show10("CCCC");
    }
}
class BB implements AA{
    @Override
    public void showA() {
        System.out.println("AAAA");
    }
}

public class Test {
    public static void main(String[] args) {
        BB b = new BB();
        b.showA();
        b.show10B();
        b.show10C();
    }
}

练习:接口,静态

  • 编写步骤
  1. 定义接口A,普通类B实现接口A。
  2. A接口中,定义抽象方法showA。
  3. A接口中,定义私有静态方法show10(String str),循环打印10次str。
  4. A接口中,定义静态方法showB(),showC(),分别调用show10方法,传入参数。
  5. B类中,定义静态方法showD
  6. 测试类中,使用A接口,调用静态showB()方法,showC()方法,
  7. 测试类中,使用B类,调用showA方法,showD方法。
interface AAA{
    public abstract void showA();

    public static void showB() {
        System.out.println("static BBBB");
        show10("BBBB");
    }
    public static void showC(){
        System.out.println("static CCCC");
        show10("CCCC");
    }
    private static void show10(String str){
        for (int i = 0; i < 10; i++) {
            System.out.println(str + " ");
        }
        System.out.println();
    }
}

class BBB implements AAA{

    @Override
    public void showA() {
        System.out.println("AAA");
    }
    public void showD(){
        System.out.println("DDDD");
    }
}

public class Test {
    public static void main(String[] args) {
        AAA.showB();
        AAA.showC();
        BBB bbb = new BBB();
        bbb.showA();
        bbb.showD();
    }
}

练习:接口,多态

输出:star:星星一闪一闪亮晶晶\n =======\n sun:太阳引着9大行星旋转\n sun:光照八分钟,到达地球

编写步骤

  1. 定义接口Universe,提供抽象方法doAnything。
  2. 定义普通类Star,提供成员发光shine方法
  3. 定义普通类Sun,继承Star类,实现Universe接口
  4. 测试类中,创建Star对象,调用shine方法
  5. 测试类中,多态的方式创建Sun对象,调用doAnything方法,向下转型,调用shine方法。
interface Universe{
    public abstract void doAnything();
}
class Star{
    public void shine(){
        System.out.println("star:星星一闪一闪亮晶晶");
    }
}
class Sun extends Star implements  Universe{
    @Override
    public void doAnything() {
        System.out.println("sun:太阳吸引着9大行星旋转");
    }
    @Override
    public void shine() {
        System.out.println("sun:光照八分钟,到达地球");
    }
}

public class Test {
    public static void main(String[] args) {
        Star s = new Star();
        s.shine();
        System.out.println("====================");
        Universe universe = new Sun();
        universe.doAnything();
        Sun sun = (Sun)universe;
        sun.shine();
    }
}

内部类

练习:需求实现

  • 定义HandleAble接口,具备一个处理字符串数字的抽象方法方法HandleString(String num)。

    • 处理方式1:取整数部分。
    • 处理方式2:保留指定位小数,四舍五入。
  • 开发提示:

    • 匿名内部类[接口不能带方法体可以匿名内部类]的方式,调用所有抽象方法
interface HandleAble{
    String handleString(String str);
}

public class Test {
    public static void main(String[] args) {
        String str = "23.23456789";
        System.out.println("原字符串是:" + str);
        HandleAble s1 = new HandleAble() {
            @Override
            public String handleString(String str) {
                return str.substring(0,str.indexOf("."));
            }
        };
        System.out.println("取整后:" + s1.handleString(str));

        int num = 4;

        HandleAble s2 = new HandleAble() {
            @Override
            public String handleString(String str) {

                int i = str.indexOf(".") + num + 1;
                char c = str.charAt(i);
                //System.out.println(c);

                if (c <= '4') {
                    return str.substring(0, i).toString();
                } else {
                    char c1 = (char) (str.charAt(str.indexOf(".") + num) + 1);
                    return str.substring(0, i - 1) + c1;

                }
            }
        };
        String sss = s2.handleString(str);
        System.out.println("保留" + num + "位小数后:" + sss);
    }
}

练习:需求实现

  • 模拟上课出勤情况。
  • 定义学生类:

    • 属性:姓名,出勤。
    • 提供基本的构造方法和get方法,set方法。
  • 定义讲师类:

    • 属性:姓名。
    • 提供基本的构造方法和get方法,set方法
    • 成员方法:点名方法,设置每一位的学生出勤情况。假设,小明今日未出勤。
  • 定义课程类:

    • 属性:课程名称,讲师,学生集合。
    • 提供基本的构造方法和get方法,set方法
    • 成员方法:show方法,打印课程信息,老师姓名,学生是否上课情况。

课程名称:Java
授课老师:张老师
上课:小红
上课:小亮
旷课:小明

public class Test {
    public static void main(String[] args) {
        Student s = new Student("小红");
        Student s1 = new Student("小亮");
        Student s2 = new Student("小明");
        ArrayList<Student> arr = new ArrayList<>();
        arr.add(s);
        arr.add(s1);
        arr.add(s2);
        Teacher t = new Teacher("张老师");
        Course course = new Course("java",t,arr);
        t.dianming(arr);
        course.show();

    }
}

class Student{
    private String name;
    private boolean come;

    public Student() {
    }

    public Student(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isCome() {
        return come;
    }

    public void setCome(boolean come) {
        this.come = come;
    }
}
class Teacher{
    private String name;
    // 点名方法,设置每一位的学生出勤情况。假设,小明今日未出勤
    public void dianming(ArrayList<Student> arr){
        for (int i = 0; i < arr.size(); i++) {
            Student student = arr.get(i);
            if (!student.getName().equals("小明")){
                student.setCome(true);
            }
        }
    }
    public Teacher() {
    }

    public Teacher(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
class Course{
    private String name;
    private Teacher t;
    private ArrayList<Student> arr;

    public Course() {
    }

    public Course(String name, Teacher t, ArrayList<Student> arr) {
        this.name = name;
        this.t = t;
        this.arr = arr;
    }
    public void show(){
        System.out.println("课程名称:" + name);
        System.out.println("授课老师:" + t.getName());
        for (int i = 0; i < arr.size(); i++) {
            Student student = arr.get(i);
            String name = student.getName();
            if (student.isCome()) {
                System.out.println("上课: " + name);
            } else {
                System.out.println("旷课: " + name);
            }
        }
    }
}

练习:需求实现

  • 模拟接待员接待用户,根据用户id,给用户分组。
  • 定义接口Filter:
    • 提供抽象方法filterUser(User u)
  • 定义用户类:
    • 属性:用户类型,用户id
    • 提供基本的构造方法和get方法,set方法
  • 定义接待员类:
    • 属性:接口Filter
    • 提供基本的构造方法和get方法,set方法
    • 成员方法:接待用户方法,设置用户类型。
  • 测试类:
    • 初始化50个User对象,id为1-50。
    • 创建三个接待员对象。
      • 第一个接待员,设置接待规则,将10-19号用户类型设置为v1。
      • 第二个接待员,设置接待规则,将20-29号用户类型设置为v2。
    • 遍历用户集合,给用户分区。
public class Test {
    public static void main(String[] args) {

        ArrayList<User> ulist = new ArrayList<>();
        for (int i = 1; i <= 50; i++) {
            ulist.add(new User(i));
        }

        System.out.println("未分组:");
        System.out.println(ulist);

        Reception r1 = new Reception();
        Reception r2 = new Reception();
        Reception r3 = new Reception();
        r1.setF(new Filter() {
            @Override
            public void filterUser(User u) {
                if (u.getId() >= 10 && u.getId() < 20)
                    u.setType("v1");
            }
        });

        r2.setF(new Filter() {
            @Override
            public void filterUser(User u) {
                if (u.getId() >= 20 && u.getId() < 30)
                    u.setType("v2");
            }
        });

        for (int i = 0; i < ulist.size(); i++) {
            User user = ulist.get(i);
            r1.recept(user);
            r2.recept(user);
            r3.recept(user);
        }
        System.out.println("已分组:");
        for (int i = 0; i < ulist.size(); i++) {
            User user = ulist.get(i);
            if (i % 9 == 0) {
                System.out.println();
            }
            System.out.print(user + " ");
        }

    }
}

class Reception {

    Filter f;

    public Filter getF() {
        return f;
    }

    public void setF(Filter f) {
        this.f = f;
    }

    public void recept(User u) {
        if (u.getType() != null)
            return;
        if (f != null) {
            f.filterUser(u);
            return;
        } else {
            u.setType("A");
        }
    }
}

class User {

    private String type;

    private int id;

    public User(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return id + "-" + type;
    }
}

interface Filter {
    public abstract void filterUser(User u);
}

练习:需求实现

  • 模拟工人挑苹果。

  • 定义苹果类:

    • 属性:大小,颜色。
    • 提供基本的构造方法和get方法,set方法
  • 定义接口CompareAble:

    • 定义默认方法compare,挑选较大苹果。
  • 定义接口实现类Compare。

  • 定义工人类:

    • 成员方法:挑选苹果Apple pickApple(CompareAble,Apple a1,Apple a2)。
  • 测试类:

    • 创建Worker对象。
    • 创建两个Apple对象,一个Apple(5,”青色”),一个Apple(3,”红色”)
    • 默认挑选大的苹果,打印苹果信息。
    • 指定颜色挑选,通过匿名内部类实现。
  • 代码实现,效果所示:

默认挑大的:
5.0 - 青色
挑红的:
3.0 - 红色

interface CompareAble{
    default Apple compare(Apple a1, Apple a2){
        return a1.getSize() > a2.getSize() ? a1 : a2;
    }
}

class Apple{
    private double size;
    private String color;

    public Apple() {
    }

    public Apple(double size, String color) {
        this.size = size;
        this.color = color;
    }

    public double getSize() {
        return size;
    }

    public void setSize(double size) {
        this.size = size;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Apple{" +
                "size=" + size +
                ", color='" + color + '\'' +
                '}';
    }
}

class Worker{
    public Apple pickApple(CompareAble c, Apple a1, Apple a2){
        Apple compare = c.compare(a1,a2);
        return compare;
    }


public class Test {
    public static void main(String[] args) {
        Worker worker = new Worker();
        Apple apple1 = new Apple(5, "青色");
        Apple apple2 = new Apple(3, "红色");
        System.out.println("默认挑大的:");
        Apple apple = worker.pickApple(new Com(), apple1, apple2);
        System.out.println(apple);

        System.out.println("挑红的:");
        Apple apple3 = worker.pickApple(new Com(){
            @Override
            public Apple compare(Apple a1, Apple a2) {
                return "红色".equals(a1.getColor()) ? a1 : a2;
            }
        },apple1,apple2);
        System.out.println(apple3);
    }
    }
}

class Com implements CompareAble {

}

数组习题

练习:需求实现

模拟在一副牌中,抽取第1张,第5张,第50张扑克牌。

输出:黑桃A 黑桃5 方片J

public class Test {
    public static void main(String[] args) {
        String[] poker = getPoker();
// 抽取指定的三种扑克牌
        int num1 = 1;
        int num2 = 5;
        int num3 = 50;
        String[] pk3 = get3(poker , num1 ,num2,num3);
        // 打印抽取的牌
        for (int i = 0; i < pk3.length; i++) {
            System.out.print(pk3[i] + " ");
        }
    }
    private static String[] get3(String[] poker, int i, int i2, int i3){
        String[] pk3 = new String[3];
        pk3[0] = poker[i - 1];
        pk3[1] = poker[i2 - 1];
        pk3[2] = poker[i3 - 1];
        return pk3;
    }
    private static String[] getPoker(){
        String[] colors={"黑色","红桃","梅花","方块"};
        String[] nums={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
        String[] poker = new String[54];
        int index = 0;
        for (int i = 0; i < colors.length; i++) {
            for (int j = 0; j < nums.length; j++) {
                poker[index] = colors[i] + nums[j];
                index++;
            }
        }
        poker[52] = "小王";
        poker[53] = "大王";

        return poker;
    }
}

练习:需求实现

定义equals方法,比较数组内容是否完全一致。

开发提示:

  • 长度一致,内容一致,定义为完全一致。
public class Test {
    public static void main(String[] args) {

        int[] arr = {1,2,3,4,3,2,1};
        int[] arr2 = {1,2,3,4,3,2,1};
        System.out.println(" 是否一致:" +equals(arr ,arr2));

    }
    //  比较数组的内容
    public static boolean equals(int[] arr1, int[] arr2) {
        // 长度不同,返回false
        if (arr1.length != arr2.length) {
            return false;
        }

        //
        for (int i = 0; i < arr1.length; i++) {
            // arr1[i] 和 arr2[i]比较
            /*
             * 所有元素都相同才相同,也就是只要有一个不同,这两个数组就是不同
             */
            if (arr1[i] != arr2[i]) {
                return false;
            }
        }
        return true;
    }
}

异常&线程习题

练习:异常的体系

1.请描述异常的继承体系
异常继承体系:异常的根类是java.lang.Throwable。其下有两个子类:java.lang.Errorjava.util.Exception
Exception又分为编译时期异常:checked异常
与运行时期异常:runtime异常

2.请描述你对错误(Error)的理解
Error:表示不可修复的恶性的错误,只能通过修改菜吗规避错误的产生,通常是系统级别的,所以很严重。

3.描述你对异常(Expection的理解)
Exception:表示可修复的良性(相对于错误)的异常,异常产生后程序员可以并且通过代码的方式修正,使程序继续运行,是必须要处理的。

4.描述你对运行时异常(RuntimeException)的理解
运行时期异常:runtime异常。在运行时期,检查异常. 在编译时期,运行异常不会编译器检测(不报错)

练习:throw与throws的区别

1.请描述throw的使用位置,作用是什么?
throw关键字通常用在方法体中,并且抛出一个异常对象。程序在执行到throw语句时立即停止,后面语句都不执行

2.请描述throws的使用位置,作用是什么?
throws关键字通常被应用在声明方法时,用来指定可能抛出的异常。多个异常可以使用逗号隔开。当在主函数中调用该方法时,如果发生异常,就会将异常对象抛给方法调用处

练习:异常的处理方式

1.异常处理方式有几种,分别是什么
异常的处理方式有两种,分别是使用 throwstry...catch...finally

2.详细阐述每种方式对异常是如何处理的
throws用在方法的声明上后接异常类名,是把异常抛给调用者进行处助理
try…catch…finally是捕获异常,自己处理,处理完毕后面的程序可以继续运行
try代码块中是可能出现异常的代码
catch代码块,是遇到异常,对异常进行处理的代码
finally代码块无论是否发生异常,都必须执行的代码,用于释放资源

练习:常见异常,及产生原因

请列举常见异常,并说明产生原因

NullPointerException:空指针异常
当应用试图在要求使用对象的方法使用了null时,抛出该异常;譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度

ArrayIndaexOutOfBoundsException:数组索引越界异常
当对数组的索引值为负数或大于等于数组大小时抛出此异常。

ArithmeticException:算术运算异常
程序中出现了除以零这样的运算就会出这样的异常,对这种异常,大家就要好好检查一下自己程序中涉及到数学运算的地方,公式是不是有不妥了

NumberFormatException:数字格式异常
当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常

练习:并行、并发概念

请简单描述什么是并行,什么是并发?

并行:指两个或多个事件在同一时刻发生(同时发生)。
并发:指两个或多个事件在同一个时间段内发生。

你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不 支持并行。
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。

并发的关键是你有处理多个任务的能力,不一定要同时。
并行的关键是你有同时处理多个任务的能力。
它们最关键的点就是:是否是『同时』

练习:进程概念、线程概念、线程与进程联系

请描述什么是进程,什么是线程,进程与线程之间的关系,并举例说明

进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。

线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。

一个程序运行后至少有一个进程,一个进程中可以包含多个线程, 但一个进程中至少包含一个线程。比如使用迅雷软件下载网络文件时,同时下载多个文件,就使用到了多线程下载。

练习:自定义异常类

请使用代码实现
每一个学生(Student)都有学号,姓名和分数,分数永远不能为负数
如果老师给学生赋值一个负数,抛出一个自定异常

// 1.定义异常类NoScoreException,继承RuntimeException 提供空参和有参构造方法
public class NoScoreException extends RuntimeException {
    //  空参构造
    public NoScoreException() {
            super();
    }
    // 有参构造
    public NoScoreException(String message) {
            super(message);
     }
/* 2.定义学生类(Student)
   a)属性:name,score
   b)提供空参构造
   c)提供有参构造;
    i.使用setXxx方法给名称和score赋值
   d)提供setter和getter方法
    ii.在setScore(int score)方法中
    1.首先判断,如果score为负数,就抛出NoScoreException,异常信息为:分数不能为负数:xxx.
    2.然后在给成员score赋值.*/
public class Student {
    private String name;
    private int score;
    // 空参构造
    public Student() {
        super();
    }
    // c)提供有参构造;
// i.使用setXxx方法给名称和score赋值
    public Student(String name,int score){
        setName(name);
        setScore(score);
    }
// d)提供setter和getter方法

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }
    // i.在setScore(int score)方法中
    public void setScore(int score) {
// 1.首先判断,如果score为负数,就抛出NoScoreException,异常信息为:分数不能为负数:xxx.
    if(score <0){
       throw new NoScoreException(":分数不能为负数:"+score);
    }
// 2.然后在给成员score赋值.
        this.score = score;
    }
}
    /*
3.定义测试类Test9
 a)提供main方法,在main方法中
  i.使用满参构造方法创建Student对象,分数传入一个负数,运行程序
  ii.由于一旦遇到异常,后面的代码的将不在执行,所以需要注释掉上面的代码
  iii.使用空参构造创建Student对象
  iv.调用setScore(int score)方法,传入一个正数,运行程序
  v.调用setScore(int score)方法,传入一个负数,运行程序
 */
public class Test9 {
    public static void main(String[] args) {
//  i.使用满参构造方法创建Student对象,分数传入一个负数,运行程序
//  Student s = new Student("景甜", -10);
//  ii.由于一旦遇到异常,后面的代码的将不在执行,所以需要注释掉上面的代码

//  iii.使用空参构造创建Student对象
        Student s = new Student();
//  iv.调用setScore(int score)方法,传入一个正数,运行程序
        s.setScore(100);
//  v.调用setScore(int score)方法,传入一个负数,运行程序
        s.setScore(-5);
    }
}

网络通信概述&TCP协议习题

练习:ip地址和端口号概念

描述:
一、请写出IP地址的概念:
IP地址:互联网协议地址(Internet Protocol Address), 俗称IP.IP地址用来给一个网络中的计算机设备做唯一的编号.

二、请写出端口号的概念:
端口号: 端口号用来给计算机里的应用程序(进程)做唯一的标识,用2个字节表示的整数,取值范围0~65535.

练习:UDP协议

判断下列说法是否正确:( X )

由于UDP面向无连接的协议,可以保证数据完整性,因此在传输重要数据时采用UDP协议.
判断错误, 因为面向无连接,容易丢失包,所以不能保证数据完整.

练习:TCP协议

TCP协议中”三次握手”,第一次握手指的是什么:

第一次握手:客户端向服务器发送请求,等待服务器确认

练习:TCP网络协议

需求说明:创建新项目,按以下要求编写代码:

在项目下创建TCP 服务器端 端口号为8888
1: 等待客户端连接 如果有客户端连接 获取到客户端对象
2: 获取到客户端对象之后 当前在服务器读取数据客户端传送数据

public class TCPServer {
   public static void main(String[] args) throws Exception {
      //1创建服务器对象 
      ServerSocket  ss = new ServerSocket(8888);
      //2等待客户端连接   如果有客户端连接  获取到客户端对象 
      Socket socket = ss.accept();
      //3当前在服务器中  要读取数据  需要输入流  流由谁提供 客户端
      InputStream in = socket.getInputStream();//获取输入流
      //4:读数据
      int len;
      byte[] buffer = new byte[1024];
      while((len=in.read(buffer))!=-1){
          System.out.println(new String(buffer, 0, len));
      }
      //释放资源
      in.close();
//       ss.close();服务器一般不会关闭
   }
}
需求说明:创建新项目,按以下要求编写代码:

在项目下创建TCP 客户端
访问之前创建的服务器端,服务器端ip127.0.0.1 端口号8888
1: 客户端连接服务器,并发送 hello.服务器,我是客户端.
2: 开启上一题服务器,等待客户端连接,客户端连接并发送数据

public class TCPClient {
  public static void main(String[] args) throws Exception {
      //创建 Socket客户端对象
      Socket socket = new Socket("127.0.0.1", 8888);
      //写数据  需要输出流  谁提供 客户端
      OutputStream out = socket.getOutputStream();
      //写数据
      out.write("hello.服务器,我是客户端.".getBytes());
      //释放资源
      out.close();
      socket.close();
  }
}